package tv.acgn.advertisement.servicebase.advice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.NoHandlerFoundException;
import tv.acgn.advertisement.servicebase.exception.AbstractAdSysBusinessException;
import tv.acgn.advertisement.servicebase.vo.CommonResponse;

/**
 * @program: advertisement-ad-service-base-advice
 * @description: 基础全局异常处理类 所有基础的业务异常都需要在此做出处理
 * 以返回友好的错误信息到前台
 * @author: junG
 * @create: 2019-04-23 01:05
 **/

@RestControllerAdvice
@Slf4j
public class GlobalExceptionResolverAdvice {

    /**
     *
     * @author junG
     * @description 业务类异常捕获处理
     * @date 1:50 2019/4/23
     * @param [request, response, adSysException]
     * @return 服务器内部错误500 {@link HttpStatus.INTERNAL_SERVER_ERROR}
     */
    @ExceptionHandler(value = AbstractAdSysBusinessException.class)
    @ResponseStatus(code= HttpStatus.INTERNAL_SERVER_ERROR)
    public CommonResponse<AbstractAdSysBusinessException> handlerAdSysBusinessException(HttpServletRequest request,
                                                                HttpServletResponse response,
                                                                AbstractAdSysBusinessException adSysException) {
        log.error("程序运行出现业务异常 {}",adSysException);
        CommonResponse<AbstractAdSysBusinessException> commonResponse = new CommonResponse<>(-500, "程序运行出现业务异常");
        commonResponse.setException(adSysException);
        return commonResponse;
    }

    /**
     *
     * @author junG
     * @description 页面或视图处理器异常处理
     * @date 1:51 2019/4/23
     * @param [request, rep, e]
     * @return 页面未找到404 {@link HttpStatus.NOT_FOUND}
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(code= HttpStatus.NOT_FOUND)
    public CommonResponse<String> pageNotFound(HttpServletRequest request,HttpServletResponse rep, NoHandlerFoundException e) {
        log.info("客户{}请求的页面或视图处理器未找到 发生异常{}",request.getRemoteUser(),e);
        CommonResponse<String> commonResponse=new CommonResponse<>(-404,"请求的页面或视图处理器未找到");
        return commonResponse;
    }

    /**
     *
     * @author junG
     * @description 上传文件失败异常处理
     * @date 1:51 2019/4/23
     * @param [request, rep, e]
     * @return 服务器内部错误500 {@link HttpStatus.INTERNAL_SERVER_ERROR}
     */
    @ExceptionHandler(MultipartException.class)
    @ResponseStatus(code= HttpStatus.INTERNAL_SERVER_ERROR)
    public CommonResponse<String> uploadFileException(HttpServletRequest request,MultipartException e) {
        log.error("客户{}上传文件失败 发生异常{}",request.getRemoteUser(),e);
        CommonResponse<String> commonResponse=new CommonResponse<>(-1010,"文件上传失败 请检查文件上传设置");
        return commonResponse;
    }

    /**
     *
     * @author junG
     * @description 请求内容体 RequestBody 无法映射至接受方法内容体(SpringWeb框架 处理方法中标注@RequestBody的参数)
     * @see org.springframework.web.bind.annotation.RequestBody
     * @date 1:51 2019/4/23
     * @param [request, rep, e]
     * @return 不支持的请求体类型415 {@link HttpStatus.UNSUPPORTED_MEDIA_TYPE}
     */
    @ExceptionHandler(value = {HttpMessageNotReadableException.class})
    @ResponseStatus(code = HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    public CommonResponse<String> httpMessageErrorHandler(HttpServletRequest request, Exception e) {
        log.debug("客户{}发送请求时 请求内容体无法映射至接受方法的内容体 发生异常{}",request.getRemoteUser(),e);
        CommonResponse<String> commonResponse=new CommonResponse<>(-1011,"发送请求时 请求内容体无法映射至接受方法的内容体 请检查请求内容体是否匹配" );
        return commonResponse;
    }

    /**
     *
     * @author junG
     * @description 接受的HTTP请求 与响应方法标注的接受请求类型(SpringWeb框架 处理方法上标注的@RequestMapping 或 @GetMapping)不匹配
     * @see org.springframework.web.bind.annotation.RequestMapping
     * @date 1:51 2019/4/23
     * @param [request, rep, e]
     * @return 不允许的请求方法405 {@link HttpStatus.METHOD_NOT_ALLOWED}
     */
    @ExceptionHandler(value = {HttpRequestMethodNotSupportedException.class})
    @ResponseStatus(code = HttpStatus.METHOD_NOT_ALLOWED)
    public CommonResponse<String> httpRequestErrorHandler(HttpServletRequest request, Exception e) {
        log.debug("客户{}发送请求时 HTTP请求方式错误 请替换为正确的请求方式 发生异常{}",request.getRemoteUser(),e);
        CommonResponse<String> commonResponse=new CommonResponse<>(-1012,"发送请求时 HTTP请求方式错误 请替换为正确的请求方式");
        return commonResponse;
    }

    /**
     *
     * @author junG
     * @description 接受的HTTP请求中的参数列表 缺少必须的请求参数 (SpringWeb框架 处理方法中标注@RequestParam的参数)
     * @see org.springframework.web.bind.annotation.RequestParam
     * @date 1:51 2019/4/23
     * @param [request, rep, e]
     * @return 不允许的请求方法405 {@link HttpStatus.METHOD_NOT_ALLOWED}
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    @ResponseStatus(code = HttpStatus.BAD_REQUEST)
    public CommonResponse<String> missingServletRequestParameterException(HttpServletRequest request, Exception e) {
        log.debug("客户{}发送请求时 缺少必须的请求参数 请检查参数列表 发生异常{}",request.getRemoteUser(),e);
        CommonResponse<String> commonResponse=new CommonResponse<>(-1012,"发送请求时 缺少必须的请求参数 请检查参数列表");
        return commonResponse;
    }
}
